﻿using Controller.Enum;
using Controller.Model;
using Leeder.Logger;
using Leeder.Model.Handler;
using Leeder.Util;
using PickingGuide.Business;
using PickingGuide.Enum;
using PickingGuide.Model;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;

namespace PickingGuide.Handle
{
    public class PickingGuideHandler
    {
        public UserModel User { get; set; }
        /// <summary>
        /// 日志
        /// </summary>
        private LogOperate LogObj => Log.GetLogger(this.GetType());
        /// <summary>
        /// 货架变化
        /// </summary>
        public event Action<List<RackSetupModel>> OnRackChange;
        /// <summary>
        /// 作业队列变化事件
        /// </summary>
        public event Action<List<QueueInfoModel>> OnWorkQueueChange;
        /// <summary>
        /// 作业指示变化事件
        /// </summary>
        public event Action<QueueInfoModel> OnWorkGuideChange;
        /// <summary>
        /// 完成拣货事件
        /// </summary>
        public event Action OnComplete;
        /// <summary>
        /// 消息通知事件
        /// </summary>
        public event Action<string, MessageType> MesgNotificationEvent;
        /// <summary>
        /// 当前作业队列
        /// </summary>
        public List<QueueInfoModel> CurrentWorkQueues { get; set; }
        /// <summary>
        /// 货架队列
        /// </summary>
        public List<RackSetupModel> RackQueues { get; set; }
        /// <summary>
        /// 当前作业车辆
        /// </summary>
        public QueueInfoModel CurrentWorkInfo { get; set; }
        /// <summary>
        /// 第二个工位作业车辆
        /// </summary>
        public QueueInfoModel CurrentWorkInfo2 { get; set; }
        /// <summary>
        /// 系统配置
        /// </summary>
        public SystemSetupModel SystemSetup { get; set; }
        /// <summary>
        /// 拣货模式
        /// </summary>
        public PickingType pickingType = PickingType.Auto;
        /// <summary>
        /// TCP服务
        /// </summary>
        private TcpServer tcpServer = new TcpServer();
        /// <summary>
        /// TCP客户端1
        /// </summary>
        private TcpClientHandler tcpClient = new TcpClientHandler();
        /// <summary>
        /// TCP客户端2
        /// </summary>
        private TcpClientHandler tcpClient2 = new TcpClientHandler();
        /// <summary>
        /// PLC操作
        /// </summary>
        private PlcHandler plcHandler;
        /// <summary>
        /// IO卡
        /// </summary>
        private IOCardHelper iOCardHelper = new IOCardHelper();
        /// <summary>
        /// 爱欧控制器
        /// </summary>
        private AioiControllerHandler aioiController = new AioiControllerHandler();
        /// <summary>
        /// PLC写入队列
        /// </summary>
        private ConcurrentQueue<PlcWriteModel> PlcWriteQueue;
        /// <summary>
        /// 是否暂停
        /// </summary>
        public bool IsSuspend = true;
        /// <summary>
        /// IO卡延时检验计时
        /// </summary>
        DateTime DelayTime = new DateTime();

        private QueueInfoBLL queueInfoBLL = new QueueInfoBLL();
        private SystemSetupBLL systemSetupBLL = new SystemSetupBLL();
        private PickingSetupBLL pickingSetupBLL = new PickingSetupBLL();
        private PickingDetailBLL pickingDetailBLL = new PickingDetailBLL();
        private PlcAddresBLL plcAddresBLL = new PlcAddresBLL();
        private PlcConnectBLL plcConnectBLL = new PlcConnectBLL();
        private RackSetupBLL rackSetupBLL = new RackSetupBLL();
        private IoCarConfigBLL ioCarConfigBLL = new IoCarConfigBLL();
        private UserBLL userBLL = new UserBLL();
        private TriaConfigBLL triaConfigBLL = new TriaConfigBLL();
        private ProductionModelsBLL productionModelsBLL = new ProductionModelsBLL();

        private PickingGuideHandler(){}
        private static PickingGuideHandler instance = new PickingGuideHandler();
        public static PickingGuideHandler getInstance()
        {
            if (instance == null)
                instance = new PickingGuideHandler();
            return instance;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool Login(string userName, string password)
        {
            var user = userBLL.Login(userName, password);
            if (user != null)
            {
                User = user;
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            LogObj.Info($"系统初始化...");
            SystemSetup = systemSetupBLL.GetModel();//获取系统配置

            //是否打开IO卡
            if (SystemSetup.IoCardIsOpen)
            {
                var ioCarConfigs = ioCarConfigBLL.GetModelAll();//获取IO卡配置
                iOCardHelper.InitIOCard(ioCarConfigs, SystemSetup.IoCardCom);//初始化IO卡
                iOCardHelper.OnInputSignalChanged += OnInputSignalChanged;
                iOCardHelper.IoCardInitAction();
                //打开TCP服务
                tcpServer.StartService(SystemSetup.TcpIp, SystemSetup.TcpPort);
                tcpServer.ReceiveEvent += TcpReceiveData;
            }

            var list = rackSetupBLL.GetModelAll();//获取货架配置
            RackQueues = new List<RackSetupModel>();
            foreach (var item in list)
            {
                //重置货架状态
                item.Status = "0";
                item.UpdateTime = DateTime.Now;
                RackQueues.Add(item);
            }
            rackSetupBLL.UpdateList(RackQueues);

            //是否打开PLC
            if (SystemSetup.PlcIsOpen)
            {
                PlcWriteQueue = new ConcurrentQueue<PlcWriteModel>();
                var plcConnect = plcConnectBLL.GetModel();//获取PLC连接配置
                plcHandler = PlcHandler.getInstance();
                if (plcConnect != null)
                    plcHandler.Init(plcConnect);//PLC初始化
            }

            //是否打开爱欧控制器
            if (SystemSetup.AioiIsOpen)
            {
                aioiController._Ip = SystemSetup.AioiControllerIp;
                aioiController._Port = SystemSetup.AioiControllerPort;
                aioiController.ButtonEvent += AioiControllerButtonEvent;
                try
                {
                    tcpClient.OnReceiveData += TcpClientReceiveData;
                    tcpClient.Connect(SystemSetup.TcpConnectIp, SystemSetup.TcpConnectPort);
                }
                catch (Exception e)
                {
                    LogObj.Error($"Tcp客户端1连接异常：{e.ToString()}");
                }
                try
                {
                    tcpClient2.OnReceiveData += TcpClientReceiveData;
                    tcpClient2.Connect(SystemSetup.TcpConnectIp2, SystemSetup.TcpConnectPort2);
                }
                catch (Exception e)
                {
                    LogObj.Error($"Tcp客户端2连接异常：{e.ToString()}");
                }
            }

            if (SystemSetup != null)
                GetQueueInfo(SystemSetup.QueueLength);

            LogObj.Info($"系统初始化完成");

            //CurrentWorkInfo = GetPickingGuide(CurrentWorkQueues,1);
            //CurrentWorkInfo2 = GetPickingGuide(CurrentWorkQueues,2);
            //if (CurrentWorkInfo != null)
            //    OnWorkGuideChange?.BeginInvoke(CurrentWorkInfo, null, null);
            //else if (CurrentWorkInfo2 != null)
            //    OnWorkGuideChange?.BeginInvoke(CurrentWorkInfo2, null, null);

            if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.PLC)
            {
                PlcRead();
                PlcClear();
            }

            //如果暂停功能不激活，启动程序直接开始作业
            if (!SystemSetup.SuspendActivate)
            {
                StartWork();
            }
        }

        /// <summary>
        /// 获取系统配置
        /// </summary>
        /// <returns></returns>
        public SystemSetupModel GetSystemConfig()
        {
            return systemSetupBLL.GetModel();//获取系统配置
        }

        /// <summary>
        /// 爱欧控制器按钮事件
        /// </summary>
        /// <param name="iModel"></param>
        public void AioiControllerButtonEvent(TriggerLabelPacketModel iModel)
        {
            var now = DateTime.Now;
            var rack = RackQueues.Where(x => x.AioiAddress == iModel.Address && (x.Status == "1" || x.Status=="3")).FirstOrDefault();
            if (rack == null)
                return;
            //该按钮距离上次感应小于3秒，则不处理
            var updateTime = rack.UpdateTime == null ? DateTime.MinValue : rack.UpdateTime;
            var timspan = now.Subtract(updateTime);
            if (timspan.TotalSeconds<3)
            {
                var showinfo = rack.RackType == "1" ? CurrentWorkInfo?.BodyNum : CurrentWorkInfo2?.BodyNum;
                AioiWrite(new List<string>() { rack.AioiAddress}, showinfo);
                return;
            }
                

            rack.Status = "2";
            rack.UpdateTime = now;
            rackSetupBLL.UpdateList(RackQueues);
            OnRackChange?.BeginInvoke(RackQueues, null, null);
            var vin = rack.RackType == "1" ? CurrentWorkInfo?.VIN : CurrentWorkInfo2?.VIN;
            MesgNotificationEvent?.BeginInvoke(string.Format("工位{0}拣货成功，部品代码:{1}，拣货名称:{2}，VIN码{3}:", rack.RackType, rack.Name, rack.Code,vin), MessageType.Info, null, null);

            if (RackQueues.Where(x => (x.Status == "1" || x.Status == "3") && x.RackType == rack.RackType).Count() <= 0)
            {
                //货架1在工位1拣货，货架2在工位2拣货
                if (rack.RackType == "1")
                {
                    if (CurrentWorkInfo.Status == "2ok")
                    {
                        CurrentWorkInfo.Status = "ok";
                        MesgNotificationEvent?.BeginInvoke("拣货完成，VIN码:" + CurrentWorkInfo.VIN, MessageType.Info, null, null);
                    }
                    else
                    {
                        if (RackQueues.All(x => x.RackType == "1"))//只有工位1拣货
                        {
                            CurrentWorkInfo.Status = "ok";
                            MesgNotificationEvent?.BeginInvoke("拣货完成，VIN码:" + CurrentWorkInfo.VIN, MessageType.Info, null, null);
                        }
                        else
                        {
                            CurrentWorkInfo.Status = rack.RackType + "ok";
                            MesgNotificationEvent?.BeginInvoke("工位" + rack.RackType + "拣货完成，VIN码:" + CurrentWorkInfo.VIN, MessageType.Info, null, null);
                        }
                    }

                    CurrentWorkInfo.UpdateDate = DateTime.Now;
                    queueInfoBLL.Update(CurrentWorkInfo);
                    if (CurrentWorkInfo2 != null && CurrentWorkInfo.ID== CurrentWorkInfo2.ID)
                    {
                        //工位1和工位2同时拣一辆车的部品,更新工位2车辆的状态
                        CurrentWorkInfo2.Status = CurrentWorkInfo.Status;
                    }

                    var list = GetQueueInfo(SystemSetup.QueueLength);
                    if (list == null || list.Count <= 0)
                        return;
                    CurrentWorkInfo = GetPickingGuide(CurrentWorkQueues,int.Parse(rack.RackType));
                    SendPickingGuide(CurrentWorkInfo, int.Parse(rack.RackType));
                    
                }
                else if (rack.RackType == "2")
                {
                    if (CurrentWorkInfo2.Status == "1ok")
                    {
                        CurrentWorkInfo2.Status = "ok";
                        MesgNotificationEvent?.BeginInvoke("拣货完成，VIN码:" + CurrentWorkInfo2.VIN, MessageType.Info, null, null);
                    }
                    else
                    {
                        if (RackQueues.All(x => x.RackType == "2"))//只有工位2拣货
                        {
                            CurrentWorkInfo2.Status = "ok";
                            MesgNotificationEvent?.BeginInvoke("拣货完成，VIN码:" + CurrentWorkInfo.VIN, MessageType.Info, null, null);
                        }
                        else
                        {
                            CurrentWorkInfo2.Status = rack.RackType + "ok";
                            MesgNotificationEvent?.BeginInvoke("工位" + rack.RackType + "拣货完成，VIN码:" + CurrentWorkInfo2.VIN, MessageType.Info, null, null);
                        }
                    }
                    CurrentWorkInfo2.UpdateDate = DateTime.Now;
                    queueInfoBLL.Update(CurrentWorkInfo2);

                    if (CurrentWorkInfo != null && CurrentWorkInfo.ID == CurrentWorkInfo2.ID)
                    {
                        //工位1和工位2同时拣一辆车的部品,更新工位1车辆的状态
                        CurrentWorkInfo.Status = CurrentWorkInfo2.Status;
                    }

                    var list = GetQueueInfo(SystemSetup.QueueLength);
                    if (list == null || list.Count <= 0)
                        return;
                    CurrentWorkInfo2 = GetPickingGuide(CurrentWorkQueues, int.Parse(rack.RackType));
                    SendPickingGuide(CurrentWorkInfo2, int.Parse(rack.RackType));
                }
            }
            //if (RackQueues.Where(x => x.Status == "1").Count() <= 0)
            //{
            //    //if (SystemSetup.IoCardIsOpen)
            //    //    iOCardHelper.IoCardCompleteAction();
            //    CurrentWorkInfo.Status = "ok";
            //    CurrentWorkInfo.UpdateDate = DateTime.Now;
            //    queueInfoBLL.Update(CurrentWorkInfo);

            //    var list = GetQueueInfo(SystemSetup.QueueLength);
            //    if (list == null || list.Count <= 0)
            //        return;
            //    GetPickingGuide();
            //    SendPickingGuide(CurrentWorkInfo);
            //}
        }

        /// <summary>
        /// TCP数据接收（出荷线拣货通过旁边的气囊追溯系统发送生产信息过来，所以这里通过TCP通讯接收气囊追溯系统发送过来的信息）
        /// </summary>
        /// <param name="data"></param>
        public void TcpClientReceiveData(string data)
        {
            try
            {
                LogObj.Info($"Tcp客户端接收数据：{data}");

                var decodeConfig = triaConfigBLL.GetModel();
                QueueInfoModel queueInfoModel = new QueueInfoModel();
                queueInfoModel.Sequence = decodeConfig.SequenceLength > 0 ? int.Parse(data.Substring(decodeConfig.SequencePosition, decodeConfig.SequenceLength)) : 0;
                queueInfoModel.BodyNum = decodeConfig.CarBodyNoLength > 0 ? data.Substring(decodeConfig.CarBodyNoPosition, decodeConfig.CarBodyNoLength) : "";
                queueInfoModel.VIN = decodeConfig.VinNoLength > 0 ? data.Substring(decodeConfig.VinNoPosition, decodeConfig.VinNoLength) : "";
                queueInfoModel.PartsCode1 = decodeConfig.PartsCode1Length > 0 ? data.Substring(decodeConfig.PartsCode1Position, decodeConfig.PartsCode1Length) : "";
                queueInfoModel.CarCode = decodeConfig.CarModelCodeLength > 0 ? data.Substring(decodeConfig.CarModelCodePosition, decodeConfig.CarModelCodeLength) : "";
                queueInfoModel.CarModel = productionModelsBLL.GetCarModel(queueInfoModel.CarCode).ModelName;
                queueInfoModel.CreatedDate = DateTime.Now;

                queueInfoBLL.Add(queueInfoModel);

                MesgNotificationEvent?.BeginInvoke(string.Format("接收到连番：{0}，VIN码:{1}", queueInfoModel.Sequence, queueInfoModel.VIN), MessageType.Info, null, null);

                if (RackQueues.Where(x => x.RackType == "1" && (x.Status == "1"||x.Status=="3")).Count() > 0)
                {
                    if (SystemSetup.IoCardIsOpen)
                    {
                        //工位1拣货看板显示红色
                        RackQueues.Where(x => x.RackType == "1" && (x.Status == "1" || x.Status == "3")).ForEach(x=>x.Status="3");
                        rackSetupBLL.UpdateList(RackQueues);
                        //机柜红灯亮
                        iOCardHelper.IoCardErrorAction();
                    }
                }
                else
                {
                    //GetQueueInfo(SystemSetup.QueueLength);
                    //GetPickingGuide();
                    //SendPickingGuide(CurrentWorkInfo);
                    SetLocation(queueInfoModel);
                }
            }
            catch (Exception e)
            {
                LogObj.Error($"Tcp客户端解析数据异常：{e.ToString()}");
            }
        }

        /// <summary>
        /// IO卡输入端口状态实时监控及逻辑处理
        /// </summary>
        /// <param name="list">输入端口集合</param>
        public void OnInputSignalChanged(List<IOCardSignalModel> list)
        {
            foreach (var item in list)
            {
                LogObj.Info("IO卡(" + item.Num + ")信号触发" + item.State);
                MesgNotificationEvent?.BeginInvoke("IO卡(" + item.Num + ")信号触发:" + item.State, MessageType.Info, null, null);
                //1口和2口留给复位用，不做处理
                //2#油箱用了0口触发油箱出货，所以先屏蔽掉这部分代码
                if (item.Num == 0)
                {
                    //出荷线按复位键，重新发送最新一条拣货信息
                    if(item.State)
                    {
                        LogObj.Info("按下复位按钮");
                        GetQueueInfo(SystemSetup.QueueLength);
                        //工位1有超时部品，则工位1跳到下一辆车
                        if (RackQueues.Where(x => x.RackType == "1" && x.Status == "3").Any())
                        {                        
                            CurrentWorkInfo = GetPickingGuide(CurrentWorkQueues, 1);
                            SendPickingGuide(CurrentWorkInfo, 1);
                        }

                        //工位2有超时部品，则工位2重新拣货
                        if (RackQueues.Where(x => x.RackType == "2" && x.Status == "3").Any())
                        {
                            CurrentWorkInfo2 = GetPickingGuide(CurrentWorkQueues, 2);
                            SendPickingGuide(CurrentWorkInfo2, 2);
                        }

         
                    }
                    continue;
                }else if (item.Num == 1)
                {
                    if (item.State)
                    {
                        if (RackQueues.Where(x => x.RackType == "2" && (x.Status == "1"||x.Status=="3")).Count() > 0)
                        {
                            if (SystemSetup.IoCardIsOpen)
                            {
                                //工位2拣货看板显示红色
                                RackQueues.Where(x => x.RackType == "2" && (x.Status == "1" || x.Status == "3")).ForEach(x => x.Status = "3");
                                rackSetupBLL.UpdateList(RackQueues);
                                //机柜红灯亮
                                iOCardHelper.IoCardErrorAction();
                            }
                        }
                        else
                        {
                            GetQueueInfo(SystemSetup.QueueLength);
                            //CurrentWorkInfo = GetPickingGuide(1);
                            //SendPickingGuide(CurrentWorkInfo, 1);
                            CurrentWorkInfo2 = GetPickingGuide(CurrentWorkQueues,2);
                            SendPickingGuide(CurrentWorkInfo2, 2);
                        }
                    }
                    continue;
                }
                if (IsSuspend && SystemSetup.SuspendActivate)
                    return;
                if (!item.State)
                    continue;
                var result = RackCheck(CurrentWorkInfo, item.Num);   //检验输入口是否出货光眼
                bool result2 = true;                                 //部品检验结果，默认为true，因为有些工位不需要校验部品
                if (SystemSetup.IsPartsCheck)
                {
                    if (CurrentWorkInfo.Status == "ok")
                        result2 = true;
                    else
                        result2 = false;
                }
                if (result && result2)
                {
                    //输入口是否出货光眼,并且部品校验通过，则判断该车完成作业，跳至下一辆车
                    DelayTime = DateTime.Now;
                    if (IsSuspend && SystemSetup.SuspendActivate)
                        return;
                    CompleteToNext();
                }
                else
                {
                    //2#油箱拣货，油箱出货口的光眼，在油箱推动的过程中可能会二次误触，所以这里进行一个延时校验，当油箱触发光眼后，10秒内的触发会忽略
                    if (DelayCheck())
                    {
                        CurrentWorkInfo.Status = "unok";
                        iOCardHelper.IoCardAction("004");
                    }
                }
            }
        }

        /// <summary>
        /// 延时检验
        /// </summary>
        /// <returns></returns>
        private bool DelayCheck()
        {
            if (DelayTime.Year <= 1)
                DelayTime = DateTime.Now;
            TimeSpan ts = DateTime.Now.Subtract(DelayTime);
            double secInterval1 = ts.TotalSeconds;
            if (secInterval1 > 10)
            {
                DelayTime = DateTime.Now;
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 货架校验
        /// </summary>
        /// <param name="model"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public bool RackCheck(QueueInfoModel model,int num)
        {
            try
            {
                for (int i = 1; i <= SystemSetup.PartsQty; i++)
                {
                    string partsCode = "";
                    if (i == 1)
                        partsCode = model.PartsCode1;
                    else if (i == 2)
                        partsCode = model.PartsCode2;
                    var pickingSetup = pickingSetupBLL.GetModel(i, partsCode, model.CarCode);
                    return RackCheckDatil(pickingSetup, num);
                }
                return false;
            }
            catch (Exception ex)
            {
                LogObj.Error($"货架校验异常：{ex.ToString()}");
                return false;
            }
        }

        public bool RackCheckDatil(PickingSetupModel model,int num)
        {
            if (model == null)
            {
                LogObj.Info($"部品没有拣货配置");
                MesgNotificationEvent?.BeginInvoke("部品没有拣货配置！", MessageType.Error, null, null);
                return false;
            }
            var pickingDetails = pickingDetailBLL.GetList(model.ID);

            if (pickingDetails == null)
            {
                LogObj.Info($"部品代码({model.Code})没有拣货明细配置");
                MesgNotificationEvent?.BeginInvoke($"部品代码({model.Code})没有拣货明细配置", MessageType.Error, null, null);
                return false;
            }
            foreach (var item in pickingDetails)
            {
                var rack = rackSetupBLL.GetModel(item.RackID);
                if (rack == null)
                {
                    LogObj.Info($"部品代码({model.Code})货架配置没有找到");
                    continue;
                }

                if (rack.IoCarInNum == (num+1))
                    return true;

                Thread.Sleep(200);
            }
            return false;
        }

        /// <summary>
        /// TCP接收数据(蓝牙扫码枪)
        /// </summary>
        /// <param name="receive"></param>
        public void TcpReceiveData(string receive)
        {
            LogObj.Info($"TCP接收数据:{receive}");
            if (IsSuspend)
                return;
            var result = PartsCheck(CurrentWorkInfo, receive);
            if (result)
            {
                iOCardHelper.IoCardCompleteAction();
                CurrentWorkInfo.Status = "ok";
                MesgNotificationEvent?.BeginInvoke("扫描OK", MessageType.Info, null, null);
            }
            else
            {
                iOCardHelper.IoCardErrorAction();
            }
        }

        /// <summary>
        /// 部品校验
        /// </summary>
        /// <param name="model"></param>
        /// <param name="barCode"></param>
        /// <returns></returns>
        public bool PartsCheck(QueueInfoModel model, string barCode)
        {
            LogObj.Info($"部品校验；barCode：{barCode}");

            var pickingSetup = pickingSetupBLL.GetModel(1, model.PartsCode1, model.CarCode);
            if (pickingSetup == null )
            {
                MesgNotificationEvent?.BeginInvoke("没有找到该车型对应的拣货配置", MessageType.Error, null, null);
                LogObj.Error("没有找到该车型对应的拣货配置");
                return false;
            }

            var pickingDetails = pickingDetailBLL.GetList(pickingSetup.ID);
            if (pickingDetails == null || pickingDetails.Count == 0)
            {
                MesgNotificationEvent?.BeginInvoke("没有找到该车型对应的部品配置", MessageType.Error, null, null);
                LogObj.Error("没有找到该车型对应的部品配置");
                return false;
            }
            else
            {
                foreach (var item in pickingDetails)
                {
                    var rack = rackSetupBLL.GetModel(item.RackID);
                    if (rack != null)
                    {
                        LogObj.Debug($"记号：{rack.Code}");
                        var result = barCode.Contains(rack.Code);
                        if (result)
                        {
                            return true;
                        }
                    }
                }
                MesgNotificationEvent?.BeginInvoke("部品校验NG", MessageType.Error, null, null);
                LogObj.Error("部品校验NG");
                return false;
            }
        }

        /// <summary>
        /// 获取作业队列
        /// </summary>
        /// <param name="queueLength"></param>
        /// <returns></returns>
        public List<QueueInfoModel> GetQueueInfo(int queueLength)
        {
            if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.AIOI)
                CurrentWorkQueues = queueInfoBLL.GetModelList(queueLength);
            else
                CurrentWorkQueues = queueInfoBLL.GetModelListByCount(queueLength);

            if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
            {
                MesgNotificationEvent?.BeginInvoke("当前无作业信息！", MessageType.Error, null, null);
                return CurrentWorkQueues;
            }
            OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
            return CurrentWorkQueues;
        }

        /// <summary>
        /// 获取生产指示
        /// </summary>
        public QueueInfoModel GetPickingGuide(List<QueueInfoModel> list,int station = 1)
        {
            //if(station == 2)
            //    list.Reverse();
            LogObj.Info($"获取生产指示");
            if (pickingType == PickingType.Auto)
            {
                if (list != null && list.Count > 0)
                {
                    string condition = "";
                    if (station == 1)
                        condition = "2ok";
                    else if(station == 2)
                        condition = "1ok";
                    foreach (QueueInfoModel model in list)
                    {
                        if (model.Status == null || model.Status == "unok" || model.Status == condition)
                        {
                            MesgNotificationEvent?.BeginInvoke("获取到生产指示，VIN码:"+model.VIN, MessageType.Info, null, null);
                            return model;
                        }
                    }
                    return default;
                }
                else
                {
                    LogObj.Info($"获取不到生产指示");
                    return default;
                }
            }
            else if (pickingType == PickingType.Manual)
            {
                if (list != null && list.Count > 0)
                {
                    return list[0];
                }else { return default; }
            }
            return default;
        }

        /// <summary>
        /// 发送生产指示
        /// </summary>
        /// <param name="model">作业</param>
        /// <param name="station">工位</param>
        public void SendPickingGuide(QueueInfoModel model, int station)
        {
            if(SystemSetup.PlcIsOpen)
            {
                PlcClear();
            }
            if (pickingType == PickingType.Auto)
            {
                SendPickingGuide_Auto(model, station);
            }
            else if (pickingType == PickingType.Manual)
            {
                SendPickingGuide_Manual(model);
            }
            else
            {

            }
        }

        /// <summary>
        /// 发送拣货指示
        /// </summary>
        /// <param name="model">作业</param>
        /// <param name="station">工位</param>
        public void SendPickingGuide_Auto(QueueInfoModel model, int station)
        {
            try
            {
                if (model == null)
                    return;
                OnWorkGuideChange?.BeginInvoke(model, null, null);
                if (SystemSetup.IoCardIsOpen)
                    iOCardHelper.IoCardAwaitAction();

                MesgNotificationEvent?.BeginInvoke("工位"+station+"开始发送拣货指示，VIN码:" + model.VIN, MessageType.Info, null, null);
                for (int i = 1; i <= SystemSetup.PartsQty; i++)
                {
                    string partsCode = "";
                    if (i == 1)
                        partsCode = model.PartsCode1;
                    else if (i == 2)
                        partsCode = model.PartsCode2;

                    var pickingSetup = pickingSetupBLL.GetModel(1, partsCode, model.CarCode);
                    SendPickingGuideDatil(model, pickingSetup, station);
                }

                

                OnRackChange?.BeginInvoke(RackQueues, null, null);
                rackSetupBLL.UpdateList(RackQueues);

                //发送完成需要发送确认信号
                var plcAddres = plcAddresBLL.GetModel("SendConfirm");
                if (plcAddres != null)
                {
                    PlcWriteModel plcWriteModel = new PlcWriteModel();
                    plcWriteModel.PlcAddres = plcAddres;
                    PlcWriteQueue.Enqueue(plcWriteModel);
                    PlcWriteQueueResolve();

                    MesgNotificationEvent?.BeginInvoke("发送确认信号，VIN码:" + model.VIN, MessageType.Info, null, null);
                }
            }
            catch (Exception ex)
            {
                LogObj.Error($"PLC写入异常：{ex.ToString()}");
            }
        }

        /// <summary>
        /// 发送拣货明细
        /// </summary>
        /// <param name="queueInfo">作业</param>
        /// <param name="model">拣货配置</param>
        /// <param name="station">工位</param>
        public void SendPickingGuideDatil(QueueInfoModel queueInfo,PickingSetupModel model, int station)
        {
            if (model == null)
            {
                LogObj.Info($"部品没有拣货配置");
                MesgNotificationEvent?.BeginInvoke("部品没有拣货配置！", MessageType.Error, null, null);
                return;
            }
            var pickingDetails = pickingDetailBLL.GetList(model.ID);

            if (pickingDetails == null)
            {
                LogObj.Info($"部品代码({model.Code})没有拣货明细配置");
                MesgNotificationEvent?.BeginInvoke($"部品代码({model.Code})没有拣货明细配置", MessageType.Error, null, null);
                return;
            }

            //如果是PLC发送拣货信号，则取拣货货架地址最小地址，该地址加一个固定值，例：123货架 1货架最小输出假设D100，当前连番就输出D100 D2  D3
            PlcAddresModel plcAddresModel = new PlcAddresModel();
            plcAddresModel.ID = 0;
            if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.PLC)
            {
                int addr = 10000;
                foreach (var item in pickingDetails)
                {
                    var rack = rackSetupBLL.GetModel(item.RackID);
                    if (rack == null)
                    {
                        continue;
                    }
                    var plcAddres = plcAddresBLL.GetModel(rack.PlcAddress);
                    var add = int.Parse(plcAddres.Address);
                    if (addr > add)
                    {
                        addr = add;
                        plcAddresModel = plcAddres;
                    }
                }
                plcAddresModel.Address = (addr + SystemSetup.PlcIncrement).ToString();
            }

            //爱欧控制器写之前先把上一辆车的状态关闭清空
            if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.AIOI)
            {
                var rackList = rackSetupBLL.GetModelList(station.ToString());
                //写爱欧控制器
                List<string> addressList = new List<string>();
                foreach (var rack in rackList)
                {
                    addressList.Add(rack.AioiAddress);
                    RackQueues.Where(x => x.ID == rack.ID).FirstOrDefault().Status = "0";
                }
                rackSetupBLL.UpdateList(RackQueues);
                AioiWriteCloseAll(addressList);
            }

            foreach (var item in pickingDetails)
            {
                var rack = rackSetupBLL.GetModel(item.RackID);
                if (rack == null)
                {
                    LogObj.Info($"部品代码({model.Code})货架配置没有找到");
                    continue;
                }
                if (rack.RackType != station.ToString())
                {
                    continue;
                }

                if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.PLC)
                {
                    //发送到PLC
                    var plcAddres = plcAddresBLL.GetModel(rack.PlcAddress);
                    if (plcAddresModel.ID == plcAddres.ID)
                        plcAddres.Address = plcAddresModel.Address;

                    PlcWriteModel plcWriteModel = new PlcWriteModel();
                    plcWriteModel.PlcAddres = plcAddres;
                    PlcWriteQueue.Enqueue(plcWriteModel);
                    PlcWriteQueueResolve();

                    RackQueues.Where(x => x.ID == rack.ID).FirstOrDefault().Status = "1";
                }
                else if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.IOCARD)
                {
                    //写IO卡
                    var ioCarCode = rack.IoCarOutNum + 100;
                    LogObj.Info($"写IO卡：{rack.Name}->{ioCarCode}");
                    iOCardHelper.IoCardAction(ioCarCode.ToString());
                    RackQueues.Where(x => x.ID == rack.ID).FirstOrDefault().Status = "1";
                }
                else if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.AIOI)
                {
                    //写爱欧控制器
                    List<string> addressList = new List<string>();
                    addressList.Add(rack.AioiAddress);
                     AioiWrite(addressList, queueInfo.BodyNum);

                    RackQueues.Where(x => x.ID == rack.ID).FirstOrDefault().Status = "1";

                    MesgNotificationEvent?.BeginInvoke(string.Format("工位{0}发送拣货指示完成，部品代码:{1}，拣货名称:{2}，VIN码:{3}",station, rack.Name, rack.Code, queueInfo?.VIN), MessageType.Info, null, null);
                }

                Thread.Sleep(200);
            }
            rackSetupBLL.UpdateList(RackQueues);
        }

        /// <summary>
        /// 发送拣货指示
        /// </summary>
        public void SendPickingGuide_Manual(QueueInfoModel model)
        {
            //if (CurrentWorkInfo.Remark == null)
            //    return;
            //OnWorkGuideChange?.BeginInvoke(CurrentWorkInfo, null, null);
            //var ids = CurrentWorkInfo.Remark.Split(',');
            //foreach (var item in ids)
            //{
            //    long id;
            //    if (long.TryParse(item, out id))
            //    {
            //        var pickingSetup = pickingSetupBLL.GetModel(id);
            //        SendPickingGuideDatil(pickingSetup);
            //    }
            //}

            //OnRackChange?.BeginInvoke(RackQueues, null, null);
            //rackSetupBLL.UpdateList(RackQueues);

            //if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.PLC)
            //{
            //    //发送完成需要发送确认信号
            //    var plcAddres = plcAddresBLL.GetModel("SendConfirm");
            //    if (plcAddres != null)
            //    {
            //        PlcWriteModel plcWriteModel = new PlcWriteModel();
            //        plcWriteModel.PlcAddres = plcAddres;
            //        PlcWriteQueue.Enqueue(plcWriteModel);
            //        PlcWriteQueueResolve();
            //    }
            //}
        }

        bool IsQueueResolve = false;
        /// <summary>
        /// PLC写入处理队列
        /// </summary>
        public void PlcWriteQueueResolve()
        {
            if (IsQueueResolve)
                return;
            IsQueueResolve = true;
            Thread thread = new Thread(() =>
            {
                while (IsQueueResolve)
                {
                    if (!PlcWriteQueue.IsEmpty)
                    {
                        PlcWriteModel model;
                        PlcWriteQueue.TryDequeue(out model);
                        if (model != null)
                        {
                            Thread.Sleep(model.Delay);
                            try
                            {
                                //测试时出现写入失败的情况，所以把写入动作单独开一个任务，写失败时重写，直到写10次都没能成功写入，那就只能退出
                                int i = 0;
                                while (i < 10)
                                {
                                    var result = plcHandler.SendPlcData(model.PlcAddres, model.Value);
                                    LogObj.Info($"PLC写入->地址{model.PlcAddres.Area}{model.PlcAddres.Address}->值{model.Value}->结果{result}");
                                    if (result)
                                        break;
                                    i++;
                                    Thread.Sleep(200);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogObj.Error(ex);
                            }
                        }
                        Thread.Sleep(100);
                    }
                    else
                    {
                        IsQueueResolve = false;
                        return;
                    }
                }
            }
            );
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 爱欧控制器数据写入
        /// </summary>
        /// <param name="addressList"></param>
        public void AioiWrite(List<string> addressList,string showInfo)
        {
            ActionPacketModel action = new ActionPacketModel
            {
                EquipmentBrand = EquipmentBrandEnum.AIOI,
                LabelType = EquipmentLabelTypeEnum.AIOI_LABEL_MWU2060,
                ControllerKey = $"{aioiController._Ip}:{aioiController._Port}",
                AddressList = addressList,
                ControlModel = new DeviceActionModel
                {
                    IsUsedConfirm = true,
                    LightModel = CommCmdLightModeEnum.GREEN,
                    OpenBuzzer = DeviceBuzzerStatuEnum.SPARKLE,
                    Seq = showInfo,
                    ConfirmLightModel = CommCmdLightModeEnum.OFF,
                    ConfirmOpenBuzzer = DeviceBuzzerStatuEnum.OFF,
                    ConfirmSeq = "",
                },
            };
            aioiController.GetController().Control(action);
        }

        /// <summary>
        /// 爱欧控制器->关闭所有标签显示
        /// </summary>
        /// <param name="addressList"></param>
        public void AioiWriteCloseAll(List<string> addressList)
        {
            ActionPacketModel action = new ActionPacketModel
            {
                EquipmentBrand = EquipmentBrandEnum.AIOI,
                LabelType = EquipmentLabelTypeEnum.AIOI_LABEL_MWU2060,
                ControllerKey = $"{aioiController._Ip}:{aioiController._Port}",
                AddressList = addressList,
                ControlModel = new DeviceActionModel
                {
                    IsUsedConfirm = true,
                    LightModel = CommCmdLightModeEnum.OFF,
                    OpenBuzzer = DeviceBuzzerStatuEnum.OFF,
                    ConfirmLightModel = CommCmdLightModeEnum.OFF,
                    ConfirmOpenBuzzer = DeviceBuzzerStatuEnum.OFF,
                },
            };
            aioiController.GetController().Control(action);
        }

        /// <summary>
        /// 完成并跳下一辆车
        /// </summary>
        public void CompleteToNext()
        {
            OnComplete?.BeginInvoke(null,null);
            if (pickingType == PickingType.Auto)
            {
                if(SystemSetup.IsBatch)
                {
                    CurrentWorkInfo.Status = "#ok";
                    CurrentWorkInfo.UpdateDate = DateTime.Now;
                    queueInfoBLL.Update(CurrentWorkInfo);

                    var list = CurrentWorkQueues.Where(x => x.Status == null || x.Status == "unok" || x.Status == "work").ToList();
                    if(list.Count <= 0)
                    {
                        CurrentWorkQueues.ForEach(x => x.Status = "ok");
                        queueInfoBLL.UpdateList(CurrentWorkQueues);
                    }
                }
                else
                {
                    CurrentWorkInfo.Status = "ok";
                    CurrentWorkInfo.UpdateDate = DateTime.Now;
                    queueInfoBLL.Update(CurrentWorkInfo);
                    MesgNotificationEvent?.BeginInvoke("拣货完成，VIN码:" + CurrentWorkInfo.VIN, MessageType.Info, null, null);
                }
                if (SystemSetup.IoCardIsOpen)
                    iOCardHelper.IoCardInitAction();
                RackQueues.ForEach(x => x.Status = "0");
                rackSetupBLL.UpdateList(RackQueues);
                OnRackChange?.BeginInvoke(RackQueues, null, null);
                Thread.Sleep(200);
                GetQueueInfo(SystemSetup.QueueLength);
                CurrentWorkInfo = GetPickingGuide(CurrentWorkQueues, 1);
                SendPickingGuide(CurrentWorkInfo, 1);
                CurrentWorkInfo2 = GetPickingGuide(CurrentWorkQueues, 2);
                SendPickingGuide(CurrentWorkInfo2, 2);
            }
            else if(pickingType == PickingType.Manual)
            {
                RackQueues.ForEach(x => x.Status = "0");
                rackSetupBLL.UpdateList(RackQueues);
                if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
                {
                    MesgNotificationEvent?.BeginInvoke($"手动拣货队列已全部完成，请添加新的队列！", MessageType.Error, null, null);
                    return;
                }
                CurrentWorkQueues.RemoveAt(0);
                OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
                if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
                {
                    if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.PLC)
                    {
                        Suspend_Plc();
                        return;
                    }else if((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.IOCARD)
                    {
                        iOCardHelper.IoCardInitAction();
                    }
                }
                //GetPickingGuide();
                //SendPickingGuide(CurrentWorkInfo);
            }
        }

        /// <summary>
        /// 暂停或开始
        /// </summary>
        public bool Suspend()
        {
            IsSuspend = !IsSuspend;
            if (IsSuspend)
            {
                /************暂停作业*************/
                if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.PLC)
                {
                    Suspend_Plc();
                }
                else if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.IOCARD)
                {
                    //写IO卡
                    iOCardHelper.IoCardInitAction();
                }
                else if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.AIOI)
                {
                    //写爱欧控制器
                }
            }
            else
            {
                /************开始作业*************/
                StartWork();
            }
            return IsSuspend;
        }

        public void Suspend_Plc()
        {
            //发送到PLC
            PlcClear();
            PlcStop();
        }

        /// <summary>
        /// 开始作业
        /// </summary>
        public void StartWork()
        {
            if (SystemSetup.IoCardIsOpen)
                iOCardHelper.IoCardInitAction();
            if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.PLC)
            {
                //if(pickingType == PickingType.Auto)
                //{
                //    //发送到PLC
                //    PlcStart();
                //    GetQueueInfo(SystemSetup.QueueLength);
                //    GetPickingGuide();
                //    SendPickingGuide(CurrentWorkInfo);
                //}
                //else if(pickingType == PickingType.Manual)
                //{
                //    //发送到PLC
                //    PlcStart();
                //    Thread.Sleep(200);
                //    OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
                //    GetPickingGuide();
                //    SendPickingGuide(CurrentWorkInfo);
                //}
            }
            else if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.IOCARD)
            {
                //if (pickingType == PickingType.Auto)
                //{
                //    //写IO卡
                //    GetQueueInfo(SystemSetup.QueueLength);
                //    GetPickingGuide();
                //    SendPickingGuide(CurrentWorkInfo);
                //}
                //else if (pickingType == PickingType.Manual)
                //{
                //    //写IO卡
                //    OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
                //    GetPickingGuide();
                //    SendPickingGuide(CurrentWorkInfo);
                //}
            }
            else if ((RackCommuniType)SystemSetup.RackCommuniType == RackCommuniType.AIOI)
            {
                //写爱欧控制器
                GetQueueInfo(SystemSetup.QueueLength);
                CurrentWorkInfo = GetPickingGuide(CurrentWorkQueues, 1);
                SendPickingGuide(CurrentWorkInfo, 1);
                CurrentWorkInfo2 = GetPickingGuide(CurrentWorkQueues, 2);
                SendPickingGuide(CurrentWorkInfo2, 2);
            }
        }

        /// <summary>
        /// PLC清0
        /// </summary>
        public void PlcClear()
        {
            LogObj.Info("PLC清0");
            Task.Run(async delegate
            {
                var plcAddres = plcAddresBLL.GetModel("Suspend");
                if (plcAddres != null)
                {
                    PlcWriteModel plcWriteModel = new PlcWriteModel();
                    plcWriteModel.PlcAddres = plcAddres;
                    PlcWriteQueue.Enqueue(plcWriteModel);
                    PlcWriteQueueResolve();
                    Thread.Sleep(2000);
                    PlcWriteModel plcWriteModel2 = new PlcWriteModel();
                    plcWriteModel2.PlcAddres = plcAddres;
                    plcWriteModel2.Value = 0;
                    PlcWriteQueue.Enqueue(plcWriteModel2);
                    PlcWriteQueueResolve();
                }
            });
        }

        /// <summary>
        /// PLC暂停信号
        /// </summary>
        public void PlcStop()
        {
            LogObj.Info("PLC暂停信号");
            var plcAddres = plcAddresBLL.GetModel("Run");
            PlcWriteModel plcWriteModel = new PlcWriteModel();
            plcWriteModel.PlcAddres = plcAddres;
            PlcWriteQueue.Enqueue(plcWriteModel);
            PlcWriteQueueResolve();
        }

        /// <summary>
        /// PLC开始信号
        /// </summary>
        public void PlcStart()
        {
            LogObj.Info("PLC开始信号");
            var plcAddres = plcAddresBLL.GetModel("Run");
            PlcWriteModel plcWriteModel = new PlcWriteModel();
            plcWriteModel.PlcAddres = plcAddres;
            plcWriteModel.Value = 0;
            PlcWriteQueue.Enqueue(plcWriteModel);
            PlcWriteQueueResolve();
        }

        string LastComplete = "";
        /// <summary>
        /// PLC读取线程
        /// </summary>
        public void PlcRead()
        {
            Thread thread = new Thread(() =>
            {
                string lastHeart = "";
                LogObj.Info("PLC读取线程启动!");
                while (true)
                {
                    var plcAddresList = plcAddresBLL.GetList("OnlyRead");
                    foreach (var item in plcAddresList)
                    {
                        try
                        {
                            if (item.SignalMark == "Heart")
                            {
                                //心跳监控
                                var heart = plcHandler.GetPlcNum(item);
                                if (heart != lastHeart)
                                {
                                    LogObj.Info("心跳变化");
                                    lastHeart = heart;
                                }
                            }
                            else if (item.SignalMark == "Complete")
                            {
                                //完成信号监控
                                var complete = plcHandler.GetPlcNum(item);
                                if ((complete == "00"|| complete == "0") && LastComplete == "1")
                                {
                                    LogObj.Info($"完成信号{complete}");
                                    MesgNotificationEvent?.BeginInvoke($"作业完成，下一辆车准备！", MessageType.Info, null, null);
                                    if (IsSuspend)
                                        return;
                                    CompleteToNext();
                                }
                                LastComplete = complete;
                            }
                        }
                        catch (Exception ex)
                        {
                            LogObj.Error($"PLC读取异常：{ex.ToString()}");
                        }
                        Thread.Sleep(50);
                    }
                    Thread.Sleep(200);
                }
            });
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 队列定位
        /// </summary>
        /// <param name="model"></param>
        public void SetLocation(QueueInfoModel model)
        {
            queueInfoBLL.SetLocation(model.CreatedDate);
            if (pickingType == PickingType.Auto)
            {
                if (SystemSetup.PlcIsOpen)
                {
                    PlcClear();
                }
                RackQueues.Where(x=>x.RackType == "1").ToList().ForEach(x => x.Status = "0");
                rackSetupBLL.UpdateList(RackQueues);
                OnRackChange?.BeginInvoke(RackQueues, null, null);

                //重新定位，如果暂停功能不激活，定位完成直接开始作业
                if (!SystemSetup.SuspendActivate)
                {
                    StartWork();
                }
            }
        }

        /// <summary>
        /// 自动模式切换手动模式
        /// </summary>
        /// <param name="list"></param>
        public void AutoToManual(List<ManualSetupModel> list)
        {
            pickingType = PickingType.Manual;
            CurrentWorkQueues.Clear();
            RackQueues.ForEach(x => x.Status = "0");
            rackSetupBLL.UpdateList(RackQueues);
            OnRackChange?.BeginInvoke(RackQueues, null, null);
            foreach (var item in list)
            {
                CurrentWorkQueues.Add(new QueueInfoModel { Sequence = 999 ,CarCode = "0",BodyNum = "-----", VIN = "", CarModel = "手动拣货",CreatedDate = DateTime.Now, Remark = item.Picking1ID.ToString()+","+ item.Picking2ID.ToString() }) ;
            }

            if (!SystemSetup.SuspendActivate)
            {
                StartWork();
            }else
            {
                OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
            }
        }

        /// <summary>
        /// 手动模式切换自动模式
        /// </summary>
        public void ManualToAuto()
        {
            //pickingType = PickingType.Auto;
            //GetQueueInfo(SystemSetup.QueueLength);
            //GetPickingGuide();
            //if (IsSuspend && SystemSetup.SuspendActivate)
            //    return;
            //SendPickingGuide(CurrentWorkInfo);
        }

        /// <summary>
        /// 获取看板队列
        /// </summary>
        /// <returns></returns>
        public List<QueueInfoModel> GetQueueBoard(int queueLength)
        {
            var list = queueInfoBLL.GetModelListByCount(1);
            if(list == null || list.Count <=0)
                return null;
            var model = list[0];
            var before = queueLength / 2;
            var later = before + (queueLength % 2);
            var beforeList = queueInfoBLL.GetModelListBefore(model, before);
            var laterList = queueInfoBLL.GetModelListLater(model, later);
            laterList[0].Status = "work";
            beforeList.Reverse();
            beforeList.AddRange(laterList);
            return beforeList;
        }

        /// <summary>
        /// 前端获取作业队列
        /// </summary>
        /// <param name="queueLength"></param>
        /// <returns></returns>
        public List<WorkQueueModel> GetQueueInfoToWeb()
        {
            try
            {
                var setup = systemSetupBLL.GetModel();//获取系统配置

                if (setup.IsBatch)
                    CurrentWorkQueues = GetQueueInfo(setup.QueueLength);
                else
                    CurrentWorkQueues = GetQueueBoard(setup.QueueLength);

                if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
                    return default;

                for (int i = 0; i < CurrentWorkQueues.Count; i++)
                {
                    if (string.IsNullOrEmpty(CurrentWorkQueues[i].Status) || CurrentWorkQueues[i].Status == "work")
                    {
                        CurrentWorkQueues[i].Status = "work";
                        break;
                    }
                    else if (CurrentWorkQueues[i].Status == "unok")
                    {
                        CurrentWorkQueues[i].Status = "unok";
                        break;
                    }
                }
                List<WorkQueueModel> list = new List<WorkQueueModel>();
                foreach (var item in CurrentWorkQueues)
                {
                    WorkQueueModel model = new WorkQueueModel();
                    model.Sequence = item.Sequence.ToString("000");
                    model.Mark = GetRackName(item);
                    if (item.Status == "pass" || item.Status == "ok" || item.Status == "#ok")
                        model.Status = "1";
                    else if (item.Status == "work")
                        model.Status = "2";
                    else if (item.Status == "unok")
                        model.Status = "-1";
                    else
                        model.Status = "0";
                    list.Add(model);
                }
                return list;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 看板获取货架名称
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public string GetRackName(QueueInfoModel model)
        {
            var pickingSetup = pickingSetupBLL.GetModel(1, model.PartsCode1, model.CarCode);
            if (pickingSetup == null)
            {
                return "无配置";
            }

            var pickingDetails = pickingDetailBLL.GetList(pickingSetup.ID);
            if (pickingDetails == null || pickingDetails.Count == 0)
            {
                return "无配置";
            }
            else
            {
                foreach (var item in pickingDetails)
                {
                    var rack = rackSetupBLL.GetModel(item.RackID);
                    if (rack != null)
                    {
                            return rack.Name;
                    }
                }
                return "无配置";
            }
        }

        /// <summary>
        /// 看板获取货架编号
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public string GetRackCode(QueueInfoModel model)
        {
            var pickingSetup = pickingSetupBLL.GetModel(1, model.PartsCode1, model.CarCode);
            if (pickingSetup == null)
            {
                return "无配置";
            }

            var pickingDetails = pickingDetailBLL.GetList(pickingSetup.ID);
            if (pickingDetails == null || pickingDetails.Count == 0)
            {
                return "无配置";
            }
            else
            {
                foreach (var item in pickingDetails)
                {
                    var rack = rackSetupBLL.GetModel(item.RackID);
                    if (rack != null)
                    {
                        return rack.Code;
                    }
                }
                return "无配置";
            }
        }

        /// <summary>
        /// 看板获取货架名称
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public string GetRackName(long pickingId)
        {
            var pickingSetup = pickingSetupBLL.GetModel(pickingId);
            if (pickingSetup == null)
            {
                return "无配置";
            }
            var pickingDetails = pickingDetailBLL.GetList(pickingSetup.ID);
            if (pickingDetails == null || pickingDetails.Count == 0)
            {
                return "无配置";
            }
            else
            {
                foreach (var item in pickingDetails)
                {
                    var rack = rackSetupBLL.GetModel(item.RackID);
                    if (rack != null)
                    {
                        return rack.Name;
                    }
                }
                return "无配置";
            }
        }

        /// <summary>
        /// 看板获取货架编号
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public string GetRackCode(long pickingId)
        {
            var pickingSetup = pickingSetupBLL.GetModel(pickingId);
            if (pickingSetup == null)
            {
                return "无配置";
            }
            var pickingDetails = pickingDetailBLL.GetList(pickingSetup.ID);
            if (pickingDetails == null || pickingDetails.Count == 0)
            {
                return "无配置";
            }
            else
            {
                foreach (var item in pickingDetails)
                {
                    var rack = rackSetupBLL.GetModel(item.RackID);
                    if (rack != null)
                    {
                        return rack.Code;
                    }
                }
                return "无配置";
            }
        }

        /// <summary>
        /// 获取记号
        /// </summary>
        /// <param name="model"></param>
        /// <param name="barCode"></param>
        /// <returns></returns>
        public string GetMark(QueueInfoModel model)
        {
            var pickingSetup = pickingSetupBLL.GetModel(1, model.PartsCode1, model.CarCode);
            if (pickingSetup == null)
            {
                return "无记号";
            }
            var pickingDetails = pickingDetailBLL.GetList(pickingSetup.ID);
            if (pickingDetails == null || pickingDetails.Count == 0)
            {
                return "无记号";
            }
            else
            {
                foreach (var item in pickingDetails)
                {
                    var rack = rackSetupBLL.GetModel(item.RackID);
                    if (rack != null)
                    {
                        return rack.Code;
                    }
                }
                return "无记号";
            }
        }

        /// <summary>
        /// 获取作业对象
        /// </summary>
        /// <param name="station"></param>
        /// <returns></returns>
        public QueueInfoModel GetWorkInfoToWeb(int station)
        {
            var queueInfos = queueInfoBLL.GetModelListByStation(station);
            if (queueInfos != null )
                return queueInfos[0];
            else
                return default;
        }

        /// <summary>
        /// 获取货架
        /// </summary>
        /// <param name="model"></param>
        /// <param name="barCode"></param>
        /// <returns></returns>
        public List<RackSetupModel> GetRackList(QueueInfoModel model,int station)
        {
            return  rackSetupBLL.GetModelList(station.ToString());
        }

        /// <summary>
        /// 看板获取作业对象
        /// </summary>
        /// <returns></returns>
        public QueueInfoModel GetWorkModel()
        {
            var list = queueInfoBLL.GetModelListByCount(1);
            if (list == null || list.Count <= 0)
                return null;
            var model = list[0];
            return model;
        }

        /// <summary>
        /// 关闭程序
        /// </summary>
        public void Close()
        {
            if (SystemSetup.IoCardIsOpen)
            {
                aioiController.ButtonEvent -= AioiControllerButtonEvent;
                iOCardHelper.IoCardCloseAction();
                
                //退出程序，把所有爱欧按钮关闭
                var rackList = rackSetupBLL.GetModelAll();
                //写爱欧控制器
                List<string> addressList = new List<string>();
                foreach (var rack in rackList)
                {
                    addressList.Add(rack.AioiAddress);
                }
                AioiWriteCloseAll(addressList);
                
            }
            if(SystemSetup.PlcIsOpen)
            {
                PlcClear();
                PlcStop();
            }
        }
    }
}
